﻿using Growatt.ShinebusService.Model;
using Growatt.ShinebusServiceUploadPack.Controllers;
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using TestFile;
using TestFile.Model;

namespace Growatt.UploadPacktest
{
    public class UploadPacktesthelper
    {

        public static UploadPacktesthelper instance = new UploadPacktesthelper(); 
        public async Task<FirmwareUploadInfoResponse> UploadPacktestExecute(string directoryPath, string directoryPathNew, ILogger<UpdatePackController> logger)
        {
            directoryPath = directoryPath + ('\\');
          
            String newDirectory = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(directoryPath)), directoryPathNew); //新的文件夹路径
            string folderPath = Path.GetDirectoryName(directoryPath);
            string fileName = "MD5Config.txt";
            FileChecker fileChecker = new FileChecker(folderPath, fileName);
            #region 为旧文件生成新的MD5Config.txt
            bool exists = fileChecker.FileExists();
            if (!exists)
            {
                var md5Path = Path.Combine(directoryPath, "MD5Config.txt");
                File.Create(md5Path).Close();
                string filePathUpdateConfig = Path.Combine(directoryPath, "UpdateConfig.txt"); // 替换为你的文件路径
                List<string> linesUpdateConfig = ReadLinesFromFile(filePathUpdateConfig);
                StringBuilder stringBuilder1 = new StringBuilder();
                List<ExtractedFileInfo> extractedInfo_UpdateConfig = ExtractInfo(linesUpdateConfig);
                foreach (var info in extractedInfo_UpdateConfig)
                {
                    string filePathBin = Path.Combine(directoryPath, info.OldConfigFileFullName);

                    // 读取文件并转换为字节数组
                    byte[] fileBytes = File.ReadAllBytes(filePathBin);

                    // 你可以在这里对字节数组进行进一步处理，例如计算MD5哈希
                    using (MD5 md5 = MD5.Create())
                    {
                        byte[] hashBytes = md5.ComputeHash(fileBytes);
                        string hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
                        logger.LogInformation($"{info.OldConfigFileFullName}={hash}");
                        stringBuilder1.AppendLine($"{info.OldConfigFileFullName}={hash}");
                    }
                }
                WriteBatFileutf(md5Path, stringBuilder1.ToString());
            }
            #endregion

            logger.LogInformation($"新的文件夹路径: {newDirectory}");
            if (Directory.Exists(newDirectory))
                Directory.Delete(newDirectory, true);
            Directory.CreateDirectory(newDirectory);

            string filePath = Path.Combine(directoryPath, "UpdateConfig.txt"); // 替换为你的文件路径
            string filePathOld = Path.Combine(directoryPath, "UpdateOldFw.txt"); // 替换为你的文件路径
            List<string> lines = ReadLinesFromFile(filePath);
            List<string> linesOld = ReadLinesFromFile(filePathOld);

            List<ExtractedFileInfo> extractedInfo = ExtractInfo(lines);
            List<ExtractedFileInfo> extractedInfolodWhite = ExtractInfoWhite(linesOld);
            logger.LogInformation($"旧的UpdateConfig: ");
            foreach (var info in extractedInfo)
            {
                logger.LogInformation($"{info.Prefix}={info.OldConfigFileFullName}");
                info.Head = info.OldConfigFileFullName.Substring(0, 4);
            }

            List<string> hexBinFiles = extractedInfo.Select(o => o.FileName.Split('.')[0]).ToList(); //获取所有binhex文件名
            List<string> hexBinFilesUni = ListHexBinFiles(directoryPath);

            var directoryName = Path.GetFileName(Path.GetDirectoryName(directoryPath)); //获取文件夹的名称
            logger.LogInformation($"旧的文件夹名称: {directoryName}");

            var resultGroups = FindStringsWithSamePrefix(hexBinFiles); //获取配置文件中的内容
            #region 获取替换字符
            var groupsWithMult = resultGroups.Where(o => o.Count > 1);
            var groupsWithSingleString = resultGroups.Where(o => o.Count == 1).Select(o => o.First()).ToList();//获取单个芯片版本的字符串的组
            foreach (var group in groupsWithMult)
            {
                var title = group.ToArray()[0].Substring(0, 4);

                string[] strings = group.ToArray().Select(o => string.Join("", o.Skip(4).Take(o.Length - 4))).ToArray(); // 去掉前面4个字符
                string result = ConcatenateWithoutY(strings);
                groupsWithSingleString.Add(title + result); // 加入到列表中
            }
            var directoryPathNewNew = directoryPathNew.Replace("x", "");//使用替换了xx

            List<string> substrings = groupsWithSingleString;
            var indices = FindSubstringIndices(directoryName.Replace("x", ""), substrings); //提取子字符串的索引信息
            string longString = directoryName;
            string modifiedString = directoryName;
            foreach (var index in indices)
            {
                index.Newstring = directoryPathNewNew.Substring(index.StartIndex, index.Substring.Length);
            }
            foreach (var index in indices)
            {
                var Newstring = string.Join("", (index.Newstring.Skip(4).Take(index.Newstring.Length - 4)));
                var oldtring = string.Join("", (index.Substring.Skip(4).Take(index.Newstring.Length - 4)));
                var head = index.Newstring.Substring(0, 4);
                index.Head = head;
                index.FileFullName = extractedInfo.FirstOrDefault(o => o.OldConfigFileFullName.Contains(index.Substring.Substring(0, 4))).OldConfigFileFullName;
                if (Newstring.Length >= 3)//针对多个版本号
                {
                    string template = new string('y', Newstring.Length);
                    string[] pairs = SplitIntoPairs(Newstring);
                    string[] results = GenerateStrings(template, pairs);
                    foreach (string result in results)
                    {
                        index.NewFullList.Add(head + result);
                        index.NewFullNameFileList.Add((head + result));

                    }
                }
                else
                {
                    index.NewFullList.Add(index.Newstring);
                    index.NewFullNameFileList.Add((index.Newstring));

                }
                if (oldtring.Length >= 3) //针对多个版本号
                {
                    string template = new string('y', oldtring.Length);
                    string[] pairs = SplitIntoPairs(oldtring);
                    string[] results = GenerateStrings(template, pairs);
                    foreach (string result in results)
                    {
                        index.OldFullNameList.Add(head + result);
                        index.OldFullFileNameList.Add((head + result));
                    }
                }
                else
                {
                    index.OldFullNameList.Add(index.Substring);
                    index.OldFullFileNameList.Add((index.Substring));

                }
            }
            #endregion
            List<Pat> list = new List<Pat>(); //
            foreach (var item in indices)
            {
                int index = 0;
                foreach (var item2 in item.NewFullNameFileList) //获取当前需要替换的新的字符串
                {
                    list.Add(new Pat(item.OldFullFileNameList[index], item.NewFullNameFileList[index]));
                    index++;
                }

            }
            List<ExtractedFileInfo> extractedInfoNew = new List<ExtractedFileInfo>();
            foreach (var item in extractedInfo)
            {

                var val = list.FirstOrDefault(o => item.OldConfigFileFullName.Contains(o.OldFile));
                if (val != null)
                {
                    var ex = "." + item.OldConfigFileFullName.Split('.')[1];
                    ExtractedFileInfo extractedFileInfo = new ExtractedFileInfo(item.Prefix, val.NewFile + ex, val.NewFile + ex);
                    extractedInfoNew.Add(extractedFileInfo);
                }
            }
            logger.LogInformation($"新的UpdateConfig: {directoryPathNew}");

            #region 生成新的UpdateConfig.txt
           
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var info in extractedInfoNew)
            {
                stringBuilder.AppendLine($"{info.Prefix}={info.OldConfigFileFullName}");
                logger.LogInformation($"{info.Prefix}={info.OldConfigFileFullName}");
            }
            WriteBatFileutf(Path.Combine(newDirectory, "UpdateConfig.txt"), stringBuilder.ToString());
            #endregion

            #region 生成新的MD5Config.txt
            logger.LogInformation($"新的MD5: {extractedInfo}");
            string filePathUpdateConfigNew = Path.Combine(newDirectory, "MD5Config.txt"); // 替换为你的文件路径
            StringBuilder stringBuilder_extractedInfoNew = new StringBuilder();

            var listNewFile = extractedInfoNew.Select(o => o.OldConfigFileFullName).ToList();

            #region 获取OA的文件信息
            var FirmwareUploadInfoResponse = await GetOAFileUrlsHelper.
                  GetOAFileUrlsHelperInstance.
                  GetOAFileUrls(listNewFile, newDirectory);
            if (FirmwareUploadInfoResponse.UploadStatus != 1)
            {
                throw new Exception(FirmwareUploadInfoResponse.Message);
                //return new FirmwareUploadInfoResponse(newDirectory, 0, FirmwareUploadInfoResponse.Message);
            }
            #endregion
            foreach (var info1 in extractedInfoNew)
            {
                string filePathBin = Path.Combine(newDirectory, info1.OldConfigFileFullName);

                // 读取文件并转换为字节数组
                byte[] fileBytes = File.ReadAllBytes(filePathBin);

                // 你可以在这里对字节数组进行进一步处理，例如计算MD5哈希
                using (MD5 md5 = MD5.Create())
                {
                    byte[] hashBytes = md5.ComputeHash(fileBytes);
                    string hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
                    logger.LogInformation($"{info1.OldConfigFileFullName}={hash.ToUpper()}");
                    stringBuilder_extractedInfoNew.AppendLine($"{info1.OldConfigFileFullName}={hash.ToUpper()}");
                }
            }
            WriteBatFileutf(filePathUpdateConfigNew, stringBuilder_extractedInfoNew.ToString());
            #endregion

            //-U结尾的文件不需要生成oldfw
            if (!directoryPathNew.Contains("-U"))
            {
                #region 生成白名单
                var listString = extractedInfolodWhite.Select(o => o.OldConfigFileFullName).ToList(); //将文件夹里面的文件替换一下
                var listStringFinalWhite = extractedInfolodWhite.Select(o => o.OldConfigFileFullName).ToList();
                var llistString = indices.Select(o => o.Newstring).ToList();
                foreach (var item in llistString)
                {
                    var str = listString.FirstOrDefault(o => o.StartsWith(item.Substring(0, 4)));
                    if (str != null)
                    {
                        listStringFinalWhite.Add(item.PadRight(str.Length, 'y')); //如果找到了，就替换掉原来的字符串
                    }
                    else
                    {
                        listStringFinalWhite.Add(item); //如果没有找到，就直接加进去
                    }
                }
                var resultGroupsWhite = FindStringsWithSamePrefix(listStringFinalWhite);
                logger.LogInformation($"White: {directoryPathNew}");
                var indexWhite = 0;
                StringBuilder sb = new StringBuilder();

                foreach (var group in resultGroupsWhite)
                {
                    var title = group.ToArray()[0].Substring(0, 4);

                    string[] strings = group.ToArray().Select(o => string.Join("", o.Skip(4).Take(o.Length - 4))).ToArray(); // 去掉前面4个字符
                    Dictionary<string, HashSet<string>> substringsDict = new Dictionary<string, HashSet<string>>();

                    // 固定长度为2
                    int length = 2;

                    // 遍历每个字符串，确定可以分割的索引范围
                    foreach (var str in strings)
                    {
                        for (int startIndex = 0; startIndex < str.Length; startIndex += length)
                        {
                            string key = $"{startIndex}-{startIndex + 1}";
                            if (startIndex + length <= str.Length)
                            {
                                ExtractSubstrings(strings.ToList(), substringsDict, startIndex, length, key);
                            }
                        }
                    }
                    List<List<string>> listVersionNum = new List<List<string>>();
                    // 输出结果
                    foreach (var kvp in substringsDict)
                    {
                        listVersionNum.Add(kvp.Value.ToList());
                      //  logger.LogInformation($"{kvp.Key}: {string.Join(", ", kvp.Value)}");
                    }
                    List<string> subResult = ConcatenateLists(listVersionNum);
                    foreach (var sub in subResult)
                    {
                        indexWhite++;
                        extractedInfolodWhite.Add(new ExtractedFileInfo((indexWhite).ToString(), title + sub, title + sub));
                        sb.AppendLine($"{indexWhite}={title + sub}");
                        //logger.LogInformation($"{indexWhite}={title + sub}");
                    }

                }
                WriteBatFileutf(Path.Combine(newDirectory, "UpdateOldFw.txt"), sb.ToString());
                #endregion
            }
            return new FirmwareUploadInfoResponse(newDirectory, 1, "上传成功!");
        }
        string[] SplitIntoPairs(string input)
        {
            string[] pairs = new string[input.Length / 2];
            for (int i = 0, j = 0; i < input.Length; i += 2, j++)
            {
                pairs[j] = input.Substring(i, 2);
            }
            return pairs;
        }

        string[] GenerateStrings(string template, string[] pairs)
        {
            string[] results = new string[pairs.Length];
            for (int i = 0; i < pairs.Length; i++)
            {
                StringBuilder sb = new StringBuilder(template);
                sb.Replace("yy", pairs[i], i * 2, 2);
                results[i] = sb.ToString();
            }
            return results;
        }
        List<string> ListHexBinFiles(string path)
        {
            List<string> hexBinFiles = new List<string>();
            try
            {
                // 获取文件夹中的所有文件
                string[] files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);

                // 遍历文件并筛选出Hex和bin文件
                foreach (string file in files)
                {
                    if (file.EndsWith(".hex", StringComparison.OrdinalIgnoreCase) ||
                        file.EndsWith(".bin", StringComparison.OrdinalIgnoreCase))
                    {
                        hexBinFiles.Add(Path.GetFileName(file));
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("错误: " + e.Message);
            }
            return hexBinFiles;
        }

        /// <summary>
        /// 查找字符串列表中所有字符串的前缀相同的组
        /// </summary>
        /// <param name="strings"></param>
        /// <param name="prefixLength"></param>
        /// <returns></returns>
        /// <summary>
        /// 查找字符串列表中所有字符串的前缀相同的组
        /// </summary>
        /// <param name="strings"></param>
        /// <param name="prefixLength"></param>
        /// <returns></returns>
        List<List<string>> FindStringsWithSamePrefix(List<string> strings, int prefixLength = 4)
        {
            Dictionary<string, List<string>> prefixMap = new Dictionary<string, List<string>>();

            foreach (var s in strings)
            {
                string prefix = s.Length >= prefixLength ? s.Substring(0, prefixLength) : s;

                // 如果前缀是 "FFFF"，则不创建组
                if (prefix == "FFFF")
                {
                    continue;
                }

                if (prefixMap.ContainsKey(prefix))
                {
                    prefixMap[prefix].Add(s);
                }
                else
                {
                    prefixMap[prefix] = new List<string> { s };
                }
            }

            // 返回所有组，包括只有一个字符串的组
            var result = prefixMap.Values.ToList();

            return result;
        }
        string ConcatenateWithoutY(params string[] strings)
        {
            // 用于存储所有非 'y' 字符及其原始位置
            var allChars = new List<(char Char, int Position)>();

            // 遍历每个字符串，记录每个字符及其位置
            for (int i = 0; i < strings.Length; i++)
            {
                string s = strings[i];
                for (int j = 0; j < s.Length; j++)
                {
                    if (s[j] != 'y')
                    {
                        allChars.Add((s[j], j));
                    }
                }
            }

            // 根据字符在原始字符串中的位置排序
            allChars.Sort((a, b) => a.Position.CompareTo(b.Position));

            // 拼接字符
            string result = string.Concat(allChars.Select(c => c.Char));
            return result;
        }
        /// <summary>
        /// 获取长字符串中多个子字符串的索引位置
        /// </summary>
        /// <param name="longString"></param>
        /// <param name="substrings"></param>
        /// <returns></returns>
        List<SubstringInfo> FindSubstringIndices(string longString, List<string> substrings)
        {
            List<SubstringInfo> indices = new List<SubstringInfo>();

            foreach (var substring in substrings)
            {
                int startIndex = longString.IndexOf(substring, StringComparison.Ordinal);
                if (startIndex != -1)
                {
                    int endIndex = startIndex + substring.Length - 1;
                    indices.Add(new SubstringInfo(substring, substring.Substring(0, 2), startIndex, endIndex));
                }
                else
                {
                    Console.WriteLine($"Substring '{substring}' not found in the long string.");
                }
            }

            return indices;
        }

        List<ExtractedFileInfo> ExtractInfo(List<string> inputStrings)
        {
            List<ExtractedFileInfo> extractedInfo = new List<ExtractedFileInfo>();

            foreach (var input in inputStrings)
            {
                // 找到等号的位置
                int equalsIndex = input.IndexOf('=');
                if (equalsIndex != -1)
                {
                    // 提取等号前面的部分
                    string prefix = input.Substring(0, equalsIndex);

                    // 提取等号后面的部分
                    string fileNameWithExtension = input.Substring(equalsIndex + 1);

                    // 找到点号的位置
                    int dotIndex = fileNameWithExtension.IndexOf('.');
                    if (dotIndex != -1)
                    {
                        // 提取点号前面的部分作为文件名
                        string fileName = fileNameWithExtension.Substring(0, dotIndex);

                        extractedInfo.Add(new ExtractedFileInfo(prefix, fileName, fileNameWithExtension));
                    }
                    else
                    {
                        throw new ArgumentException("No dot found in the file name: " + fileNameWithExtension);
                    }
                }
                else
                {

                    throw new ArgumentException($"No equals sign found in the string: {input}");
                }
            }

            return extractedInfo;
        }
        List<ExtractedFileInfo> ExtractInfoWhite(List<string> inputStrings)
        {
            List<ExtractedFileInfo> extractedInfo = new List<ExtractedFileInfo>();

            foreach (var input in inputStrings)
            {
                if (!string.IsNullOrEmpty(input))
                {
                    // 找到等号的位置
                    int equalsIndex = input.IndexOf('=');
                    if (equalsIndex != -1)
                    {
                        // 提取等号前面的部分
                        string prefix = input.Substring(0, equalsIndex).Replace(" ", "");

                        // 提取等号后面的部分
                        string fileNameWithExtension = input.Substring(equalsIndex + 1).Replace(" ", "");

                        extractedInfo.Add(new ExtractedFileInfo(prefix, fileNameWithExtension, fileNameWithExtension));

                    }
                    else
                    {
                        throw new ArgumentException($"No equals sign found in the string: {input}");

                    }
                }

            }

            return extractedInfo;
        }
        List<string> ReadLinesFromFile(string filePath)
        {
            List<string> lines = new List<string>();
            try
            {
                // 读取文件的所有行
                lines = File.ReadAllLines(filePath).ToList();
                lines.Select(o => string.IsNullOrEmpty(o)).ToList();
            }
            catch (Exception e)
            {
                throw new ArgumentException($"{filePath}读取文件时发生错误: " + e.Message);
            }
            return lines;
        }

        void ExtractSubstrings(List<string> strings, Dictionary<string, HashSet<string>> substringsDict, int startIndex, int length, string key)
        {
            if (!substringsDict.ContainsKey(key))
            {
                substringsDict[key] = new HashSet<string>();
            }

            foreach (var str in strings)
            {
                if (startIndex + length <= str.Length)
                {
                    substringsDict[key].Add(str.Substring(startIndex, length));
                }
            }
        }

        List<string> ConcatenateLists(List<List<string>> lists)
        {
            if (lists.Count == 0)
            {
                return new List<string> { "" };
            }

            List<string> currentList = lists[0];
            List<List<string>> remainingLists = lists.GetRange(1, lists.Count - 1);
            List<string> subResult = ConcatenateLists(remainingLists);

            List<string> result = new List<string>();
            foreach (string item in currentList)
            {
                foreach (string subItem in subResult)
                {
                    result.Add(item + subItem);
                }
            }

            return result;
        }
        bool WriteBatFileutf(string filePath, string fileContent)
        {
            try
            {
                if (File.Exists(filePath))
                    File.Delete(filePath);
                FileStream fs1 = new FileStream(filePath, FileMode.Create, FileAccess.Write);//创建写入文件
                StreamWriter sw = new StreamWriter(fs1, Encoding.UTF8);
                sw.WriteLine(fileContent);//开始写入值
                sw.Close();
                fs1.Close();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

    }



    /// <summary>
    /// 存储子字符串及其索引信息
    /// </summary>
    public class SubstringInfo
    {
        public string Substring { get; set; }
        public string Head { get; set; }
        public List<string> OldFullNameList { get; set; } = new List<string>();
        public List<string> OldFullFileNameList { get; set; } = new List<string>();
        public List<string> NewFullList { get; set; } = new List<string>();
        public List<string> NewFullNameFileList { get; set; } = new List<string>();
        public string SubSubstring { get; set; }
        public string Newstring { get; set; }
        public string FileFullName { get; set; }
        public int StartIndex { get; set; }
        public int EndIndex { get; set; }

        public SubstringInfo(string substring, string subsubstring, int startIndex, int endIndex)
        {
            Substring = substring;
            SubSubstring = subsubstring;
            StartIndex = startIndex;
            EndIndex = endIndex;
        }
    }

    public class ExtractedFileInfo
    {
        public string Prefix { get; set; }
        public string FileName { get; set; }
        public string OldConfigFileFullName { get; set; }
        public string Head { get; set; }

        public ExtractedFileInfo(string prefix, string fileName, string fileFullName)
        {
            Prefix = prefix;
            FileName = fileName;
            OldConfigFileFullName = fileFullName;
        }
    }
    public class Pat
    {
        public Pat(string oldFile, string newFile)
        {
            OldFile = oldFile;
            NewFile = newFile;
        }

        public string OldFile { get; set; }
        public string NewFile { get; set; }
    }
}